package com.netwit.shiro.jwt.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import java.io.UnsupportedEncodingException;
import java.util.Date;

public class JWTUtil {

    private final static Logger log = LoggerFactory.getLogger(JWTUtil.class);

    @Value("${jwt.token.access.expiration:300}")
    private static long ACCESS_TOKEN_EXP = 5 * 60;  // accessToken: 过期时间, 秒

    @Value("${jwt.token.refresh.expiration:600}")
    private static long REFERSH_TOKEN_EXP = 10 * 60; // refreshToken: 过期时间, 秒

    /**
     * 校验 token 是否正确
     * @param token 密钥
     * @param userId 用户ID
     * @param secret 用户密码
     * @return 是否成功
     */
    public static String verify(String token, String userId, String secret){
        try {
            Algorithm algorithm  = Algorithm.HMAC512(secret);
            JWTVerifier verifier = JWT.require(algorithm).withClaim("userId", userId).build();
            DecodedJWT jwt = verifier.verify(token);
            return "success";
        } catch (TokenExpiredException tee){
            log.error("[verify] - TokenExpiredException: " + tee.getMessage());
            return "TokenExpired";
        } catch (Exception e){
            log.error("[verify] - Exception: " + e.getMessage());
            return "error";
        }
    }

    /**
     * 获得 token 中的信息，无需解密也可获取
     * @param token token
     * @Param key 要获得的信息在 token 中的主键
     * @return 返回 token 中与 key 对应的值
     */
    public static String getValue(String token, String key){
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(key).asString();
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    public static String getUserId(String token){
        return getValue(token, "userId");
    }

    /**
     * 生成签名 accessToken, ACCESS_TOKEN_EXP 后过期
     * @param userId 用户ID
     * @param secret 用户密码
     * @param expiration 过期时间 - 毫秒
     * @return 加密的 token
     */
    public static String sign(String userId, String secret, long expiration) {
        try {
            Date date = new Date(System.currentTimeMillis() + expiration);
            Algorithm algorithm = Algorithm.HMAC512(secret);
            String token = JWT.create().withClaim("userId", userId).withExpiresAt(date).sign(algorithm);
            return token;
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage());
            return null;
        }
    }

    public static String accessToken(String userId, String secret){
        return sign(userId, secret, ACCESS_TOKEN_EXP * 1000);
    }

    public static String refreshToken(String userId, String secret){
        return sign(userId, secret, REFERSH_TOKEN_EXP * 1000);
    }
}
